﻿#include <QtCore/QtCore>
#include <QDebug>
#include <QMessageBox>
#include <QSettings>
#include <QTextCodec>
#include <QFile>
#include <QFileDialog>
#include <qsciscintilla.h>
#include <Scintilla.h>
#include "ConversionPlugin.h"

ConversionPlugin::ConversionPlugin(QWidget *parent, std::function<QsciScintilla* ()> func, QMenu* menu, QString pluginPath)
    : QWidget(parent),
    currentWidget(parent),
    setting(parent, pluginPath),
    doc(parent, func),
    convertPanel(doc, parent)
{
    QTranslator trans;
    if (trans.load(currentWidget->locale().language() == QLocale::Chinese ? ":/zh_tr.qm" : "")) {
        qApp->installTranslator(&trans);
    }
    SetMenuActions(menu);
    setting.ui.retranslateUi(&setting);
    convertPanel.ui.retranslateUi(&convertPanel);
}

ConversionPlugin::~ConversionPlugin()
{
}

void ConversionPlugin::SetMenuActions(QMenu *menu)
{
    menu->addAction(QObject::tr("ASCII -> HEX"), [=]() {
        ToHex();
    }, QKeySequence(PLUGIN_SHORTCUT_TOHEX));
    menu->addAction(QObject::tr("HEX -> ASCII"), [=](){
        ToString();
    }, QKeySequence(PLUGIN_SHORTCUT_TOASCII));

    menu->addAction(QObject::tr("Configuration"), [=]() {
        if (!setting.isVisible()) {
            setting.setWindowFlags(Qt::Window);
            setting.show();
        } else {
            setting.close();
        }
     }, QKeySequence(PLUGIN_SHORTCUT_CONFIG));
    menu->addSeparator();
    menu->addAction(QObject::tr("Conversion Pannel"), [=]() {
        if (!convertPanel.isVisible()) {
            convertPanel.setWindowFlags(Qt::Window);
            convertPanel.show();
        } else {
            convertPanel.close();
        }
    }, QKeySequence(PLUGIN_SHORTCUT_CVTPANNAL));
    menu->addSeparator();
    menu->addAction(QObject::tr("Save As Binary File"), [=]() {
        SaveAs();
    }, QKeySequence(PLUGIN_SHORTCUT_SAVEAS));
    QString msg =
        QString(QString("<table align='left'><tr><td>" + QObject::tr("Version: ") + "</td><td>%1</td></tr>" +
        QString("<tr><td>") + QObject::tr("Author: ") + "</td><td>%2<%3></td></tr>" + 
        QString("<tr><td>") + QObject::tr("Plugin Website:") + "</td><td><a href='%5'>%6</a></td></tr></table>")).arg(
        PLUGIN_VERSION_STR, PLUGIN_AUTHOR, PLUGIN_AUTHOR_EMAIL, PLUGIN_WEBSITE, PLUGIN_WEBSITE);
    menu->addAction(QObject::tr("About"), [=]() {
        QMessageBox::about(this, QObject::tr("ASCII-HEX Converter"), msg);
    });
}

void ConversionPlugin::SaveAs()
{
    auto filePath = QFileDialog::getSaveFileName(this, QObject::tr("Save File"));
    if (filePath.isEmpty()) {
        return;
    }
    QFile f(filePath);
    if (!f.open(QIODevice::WriteOnly)) {
        QMessageBox::information(this, PLUGIN_NAME, QObject::tr("Create File Failed."), QMessageBox::NoButton);
        return;
    }
    auto bytes = doc.GetText();
    if (f.write(bytes) != bytes.size()) {
        QMessageBox::information(this, PLUGIN_NAME, QObject::tr("Save File imcompletely."), QMessageBox::NoButton);
    }
    f.close();
}

void ConversionPlugin::ToHex()
{
    SelectInfos colInfos = doc.GetMultipleSelections(SEL_SORT_BY_POSITION);
    auto txt = doc.GetText();
    if (colInfos.size() >= 1 && !(colInfos.size() == 1 && colInfos[0].leftPos == colInfos[0].rightPos)) {
        int increaseCnt = 0;
        for (size_t i = 0; i < colInfos.size(); i++) {
            auto& col = colInfos[i];
            if (!col.Valid()) {
                continue;
            }
            auto selText = txt.mid(col.leftPos + increaseCnt, col.rightPos - col.leftPos);
            auto retText = ToHex(selText, false);
            txt.replace(col.leftPos + increaseCnt, col.rightPos - col.leftPos, retText);
            auto lastIncrCnt = increaseCnt;
            increaseCnt += (retText.length() + col.leftPos - col.rightPos);
            col.leftPos += lastIncrCnt;
            col.rightPos += increaseCnt;
        }
    } else {
        txt = ToHex(txt, true);
    }
    doc.SetText(txt);
    doc.SelectMultipleRanges(colInfos);
}

void ConversionPlugin::ToString()
{
    SelectInfos colInfos = doc.GetMultipleSelections(SEL_SORT_BY_POSITION);
    auto txt = doc.GetText();
    if (colInfos.size() >= 1 && !(colInfos.size() == 1 && colInfos[0].leftPos == colInfos[0].rightPos)) {
        int increaseCnt = 0;
        for (size_t i = 0; i < colInfos.size(); i++) {
            auto& col = colInfos[i];
            if (!col.Valid()) {
                continue;
            }
            auto selText = txt.mid(col.leftPos + increaseCnt, col.rightPos - col.leftPos);
            auto retText = ToString(selText, false);
            if (retText.isEmpty()) {
                return;
            }
            txt.replace(col.leftPos + increaseCnt, col.rightPos - col.leftPos, retText);
            auto lastIncrCnt = increaseCnt;
            increaseCnt += (retText.length() + col.leftPos - col.rightPos);
            col.leftPos += lastIncrCnt;
            col.rightPos += increaseCnt;
        }
    } else {
        txt = ToString(txt, true);
        if (txt.isEmpty()) {
            return;
        }
    }
    doc.SetText(txt);
    doc.SelectMultipleRanges(colInfos);
}

QByteArray ConversionPlugin::ToHex(const QByteArray &txt, bool fullText)
{
    setting.cfg.wholeTextConvert = fullText;
    setting.cfg.newLineType = doc.GetNewLineType();
    return Converter::AsciiToIntStr(txt, 16, setting.cfg);
}

QByteArray ConversionPlugin::ToString(const QByteArray &txt, bool fullText)
{
    std::string convertState;
    setting.cfg.wholeTextConvert = fullText;
    setting.cfg.newLineType = doc.GetNewLineType();
    auto ret = Converter::HexToAscii(txt, convertState, setting.cfg);
    if (!convertState.empty()) {
        QMessageBox::information(this, PLUGIN_NAME, QString(convertState.data()), QMessageBox::Ok);
        return QByteArray();
    }
    return ret;
}
